package slot_machine

import (
	"github.com/spf13/cast"
	global2 "longmen/server/config/global"
	"longmen/server/internal/rpc/games/common"
	imsdk2 "longmen/server/internal/rpc/tencentim/imsdk"
	utils2 "longmen/server/internal/rpc/tencentim/utils"
	"longmen/server/pkg/common/api_models"
	"longmen/server/pkg/db/redis/cache"
	"sync"
)

type SlotTable struct {
	roomID        string
	gameSate      uint32   // 游戏状态
	gameNum       uint32   // 第几轮游戏
	betUser       sync.Map //下注用户
	TotalBet      int64    // 总下注金额(分)
	stopAction    bool     // 停止下注
	handBeginTime int64    // 当前轮开始时间
	handEndTime   int64    // 当前轮结束时间
	timer         common.GameTimer
	potBet        sync.Map //本轮各位置底池下注, map[int]int64, key: potId
}

func NewSlotTable(roomID string) *SlotTable {
	var pots sync.Map
	for i := 0; i < 8; i++ {
		pots.Store(i, 0)
	}
	return &SlotTable{
		roomID: roomID,
		potBet: pots,
	}
}

// JoinTable 加入桌子
func (t *SlotTable) JoinTable() {
	var resp api_models.JoinGameResp
	var pots []*api_models.Pots
	t.potBet.Range(func(key, value interface{}) bool {
		pots = append(pots, &api_models.Pots{
			Site:      cast.ToUint32(key),
			BetAmount: cast.ToInt64(value),
		})
		return true
	})

	resp.Table = &api_models.TableInfo{
		GameNum:           t.gameNum,
		TotalBet:          t.TotalBet,
		TotalBetPlayerNum: lenOfSyncMap(&t.betUser),
		GameSate:          t.gameSate,
		Countdown:         0,
		Pots:              pots,
	}
	t.sendToClient(resp)
}

// UserBet 玩家下注
func (t *SlotTable) UserBet(buyReq *api_models.UserBetReq) bool {
	resp := &api_models.UserBetResp{}
	defer t.sendToClient(resp)
	if t.gameSate != STATE_ACTION {
		return false
	}
	if !t.userCanBet(buyReq.Uid, buyReq.Amount) {
		return false
	}
	b, balance := cache.UpdateUserGoldCache(buyReq.Uid, -buyReq.Amount)
	if !b {
		resp.Code = 2
		return false
	}
	t.TotalBet += buyReq.Amount
	resp.Balance = balance
	resp.Code = 1
	//t.broadcastMsg()
	return true
}

// userCanBet 是否可以下注
func (t *SlotTable) userCanBet(uid int, betAmount int64) bool {
	user, err := cache.GetUserFullInfo(uid)
	if err != nil {
		return false
	}
	if int64(user.Gold) < betAmount {
		return false
	}
	return true
}

// setPotBet 设置底池
func (t *SlotTable) setPotBet(potId int, chips int64) {
	bet := t.getPotBet(potId)
	t.potBet.Store(potId, bet+chips)
	t.TotalBet += chips
}

func (t *SlotTable) getPotBet(potId int) (bet int64) {
	if v, ok := t.potBet.Load(potId); ok {
		bet = cast.ToInt64(v)
	}
	return
}

func lenOfSyncMap(m *sync.Map) uint32 {
	var length uint32
	m.Range(func(key, value interface{}) bool {
		length++
		return true
	})
	return length
}

func (t *SlotTable) changeState(s uint32) {
	t.gameSate = s
}

// broadcastMsg 广播消息
func (t *SlotTable) broadcastMsg(subCmd uint32, m interface{}) {
	resp := api_models.GameMess{}
	resp.SubCmd = subCmd
	resp.Data = m
	err := imsdk2.GetSdk().BroadcastInterfaceGroupString(t.roomID, &resp, 0)
	if err != nil {
		global2.Log.Errorf("broadcastMsg error:%v", err)
	}
}

// 响应
func (t *SlotTable) sendToClient(data interface{}) {
	utils2.CallbackOkAndExt(data, t.roomID)
}
